﻿unit frmMainUnt;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  Vcl.Menus, Vcl.AppEvnts,

  Data.DB, Datasnap.DBClient,MidasLib,Clipbrd,

  frxClass, frxPreview,frxDBSet,frxBarcode, frxRich, frxDCtrl,frxGradient,frxChBox, frxOLE,
  frxExportPDF,frxExportImage, frxExportRTF, frxExportXLS, frxExportHTML,

  superobject,CustomThreadUnt,

  IdBaseComponent, IdComponent,IdHeaderList,
  IdContext,IdCustomTCPServer, IdCustomHTTPServer, IdHTTPServer,
  IdHTTP,IdIOHandler,IdIOHandlerSocket, IdSSLOpenSSL, IdIOHandlerStack, IdSSL,
  IdTCPConnection, IdTCPClient;

const
   notice_message                                         = WM_USER + $1003;
   start_printing                                         = 1001;
   remote_printing                                        = 1002;

type
  PDataBind=^TDataBind;
  TDataBind=Packed Record
    TmpDataSet:TClientDataSet;
    TmpUserData:TfrxDBDataSet;
    end;

  TfrmMain = class(TForm)
    frmIdHTTPServer: TIdHTTPServer;
    frmTrayIcon: TTrayIcon;
    frmPopupMenu: TPopupMenu;
    menu_item_exit: TMenuItem;
    frmApplicationEvents: TApplicationEvents;
    frmIdHTTPClient: TIdHTTP;
    frmIdSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL;
    menu_item_design: TMenuItem;
    menu_item_test: TMenuItem;
    menu_item_log: TMenuItem;
    menu_item_remote: TMenuItem;
    procedure frmIdHTTPServerCommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    procedure frmIdHTTPServerCreatePostStream(AContext: TIdContext;
      AHeaders: TIdHeaderList; var VPostStream: TStream);
    procedure frmIdHTTPServerDoneWithPostStream(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; var VCanFree: Boolean);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure menu_item_exitClick(Sender: TObject);
    procedure frmApplicationEventsMinimize(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure menu_item_designClick(Sender: TObject);
    procedure menu_item_testClick(Sender: TObject);
    procedure menu_item_logClick(Sender: TObject);
    procedure frmIdHTTPServerCommandError(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
      AException: Exception);
    procedure menu_item_remoteClick(Sender: TObject);
  private
    { Private declarations }
    frxReport:TfrxReport;
    frxBarCodeObject: TfrxBarCodeObject;
    frxOLEObject: TfrxOLEObject;
    frxRichObject: TfrxRichObject;
    frxDialogControls: TfrxDialogControls;
    frxCheckBoxObject: TfrxCheckBoxObject;
    frxGradientObject: TfrxGradientObject;
    frxPDFExport1: TfrxPDFExport;
    frxHTMLExport1: TfrxHTMLExport;
    frxXLSExport1: TfrxXLSExport;
    frxRTFExport1: TfrxRTFExport;
    frxJPEGExport1: TfrxJPEGExport;

    FPrintParams: ISuperObject;
    FPrintMode:Integer;
    FReportStream:TMemoryStream;
    TmpDataBindList:TThreadList;

    FRemotePrintThread:TCustomThread;

    FPrintData:UTF8String;
    FAjustRuning,
    ApplicationQuit:boolean;
    logMemo:UTF8String;
    DefaultCode,
    RemotePrintUrl,
    DefaultHost:String;
    DefaultPort:Integer;

    procedure ReadInfor;
    procedure WriteInfor;
    procedure InitialFastReport;
    procedure FinitalFastReport;
    procedure InitialHttpClient;
    procedure InitialHttpServer;

    function CreateUserDataSet(sName:String):PDataBind;
    function GetUserDataSet(sName:String):PDataBind;
    procedure DeleteDataSetAll;
    procedure SetUserDataSet(sName:String;sJsonDetia:WideString);

    function frxReportUserFunction(const MethodName: string; var Params: Variant): Variant;
    procedure frxReportGetValue(const VarName: string; var Value: Variant);

    procedure LoadReportData;
    procedure LoadReportFileProcess;
    procedure PrintReportProcess;

    procedure callHttpInterface;
    procedure AjustPrintProcess;
    procedure ProcessCustomMessage(var msg:tmessage); message notice_message;
    procedure WriteLogProcess(sFunction, sLog: UTF8String);
    procedure FRemoteOnPrint(Sender:TObject);
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;
  FLock: TRTLCriticalSection;


implementation
uses ActiveX,SimpleXmlUnt,IniFiles,shellapi;

{$R *.dfm}

procedure TfrmMain.frmIdHTTPServerCommandError(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
  AException: Exception);
begin
  WriteLogProcess('frmIdHTTPServerCommandError', AException.Message);
end;

procedure TfrmMain.frmIdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  FileExt:String;
  sFilename: string;
  sUrl: string;
begin
  AResponseInfo.CustomHeaders.Add(ConCat('Access-Control-Allow-Origin:',ARequestInfo.RawHeaders.Values['Origin']));
  AResponseInfo.CustomHeaders.Add(ConCat('Access-Control-Allow-Credentials:','true'));
  AResponseInfo.CustomHeaders.Add(ConCat('Access-Control-Allow-Method:','POST, GET, OPTIONS, DELETE'));
  AResponseInfo.CustomHeaders.Add(ConCat('Access-Control-Max-Age:','3600'));
  AResponseInfo.CustomHeaders.Add(ConCat('Access-Control-Allow-Headers:','Authorization,JSESSIONID,Origin, X-Requested-With, Content-Type, Accept'));

  if SameText(ARequestInfo.Command,'post') then  //打印，导出，
    try
      SetLength(FPrintData,ARequestInfo.PostStream.Size);
      ARequestInfo.PostStream.Read(FPrintData[1],ARequestInfo.PostStream.Size);
      if not FAjustRuning then PostMessage(handle,notice_message,start_printing,0);
      AResponseInfo.ContentText := '{"success":true}';
      AResponseInfo.WriteContent;
    except
      on e:exception do
        WriteLogProcess('frmIdHTTPServerCommandGet', e.Message);
    end;

  if SameText(ARequestInfo.Command,'get') then  //查看导出文件
    try
      sUrl := StringReplace(ARequestInfo.Document,'/','\',[rfReplaceAll, rfIgnoreCase]);
      sFilename := ExtractFilePath(Application.ExeName) + sUrl;
      if FileExists(sFilename) then
      begin
        AResponseInfo.ContentStream := TFileStream.Create(sFilename, fmOpenRead + fmShareDenyWrite);//发文件
      end
      else if CompareText(sUrl,'\demo\log.txt')=0 then
      begin
        AResponseInfo.ContentStream:= TStringStream.Create(logMemo);
        //UTF8 前面要加BOM
        AResponseInfo.ContentStream.Seek(0,0);
        AResponseInfo.ContentStream.WriteBuffer(AnsiString(#$EF#$BB#$BF)[1], 3);
        AResponseInfo.ContentStream.Seek(0,0);
      end
      else begin
          AResponseInfo.ResponseNo := 404;
          AResponseInfo.ContentText := 'Not Found ' + ARequestInfo.Document;
      end;

      FileExt:=ExtractFileExt(sFilename);
      AResponseInfo.ContentEncoding:='utf-8';
      if (CompareText(FileExt,'.html')=0) or (CompareText(FileExt,'.htm')=0)  then
        AResponseInfo.ContentType :='text/html';
      if (CompareText(FileExt,'.css')=0) or (CompareText(FileExt,'.less')=0)  then
        AResponseInfo.ContentType :='text/css';
      if CompareText(FileExt,'.txt')=0 then AResponseInfo.ContentType :='text/plain';
      if CompareText(FileExt,'.js')=0 then AResponseInfo.ContentType :='application/javascript';
      if CompareText(FileExt,'.svg')=0 then AResponseInfo.ContentType :='image/svg+xml';
      if (CompareText(FileExt,'.jpg')=0)or(CompareText(FileExt,'.jpeg')=0) then AResponseInfo.ContentType :='image/jpeg';
      if CompareText(FileExt,'.pdf')=0 then AResponseInfo.ContentType :='application/pdf';
      if CompareText(FileExt,'.rtf')=0 then AResponseInfo.ContentType :='application/x-rtf';
      if CompareText(FileExt,'.xls')=0 then AResponseInfo.ContentType :='application/vnd.ms-excel';
      if CompareText(FileExt,'.json')=0 then AResponseInfo.ContentType :='application/json';
      if CompareText(FileExt,'.fr3')=0 then AResponseInfo.ContentType :='application/octet-stream';
      AResponseInfo.WriteContent;
      AResponseInfo.Server:='nginx/1.15.0';
      AResponseInfo.CacheControl:='no-cache';
      AResponseInfo.Pragma:='no-cache';
      AResponseInfo.Date:=Now;
    except
      on e:exception do
        WriteLogProcess('frmIdHTTPServerCommandGet', e.Message);
    end;
end;

procedure TfrmMain.frmIdHTTPServerCreatePostStream(AContext: TIdContext;
  AHeaders: TIdHeaderList; var VPostStream: TStream);
begin
  VPostStream := TMemoryStream.Create;
end;

procedure TfrmMain.frmIdHTTPServerDoneWithPostStream(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; var VCanFree: Boolean);
begin
  VCanFree:=true;
end;


procedure TfrmMain.FRemoteOnPrint(Sender:TObject);
begin
  Sleep(5000); //隔5秒循环一次
  if menu_item_remote.Checked then
  if not FAjustRuning then callHttpInterface();
end;

procedure TfrmMain.callHttpInterface;
var
   TmpJson:ISuperObject;
   FParams:TStringStream;
   DataString:String;
begin
  try
  FParams := TStringStream.Create('');//创建一个包含JSON数据的变量
    try
    FParams.Position := 0;//将流位置置为0
    DataString:=frmIdHTTPClient.POST(RemotePrintUrl,FParams);
    TmpJson:=SO(DataString);
    if CompareText(TmpJson['success'].AsString,'true')=0 then
      begin
      WriteLogProcess('callHttpInterface','开始打印');
      if not FAjustRuning then
        begin
        FPrintData:=TmpJson['detail'].AsJSon(true,true);
        AjustPrintProcess();
        end;
      end else WriteLogProcess('callHttpInterface', TmpJson['msg'].AsString);
    except
    on e:exception do
      WriteLogProcess('callHttpInterface', e.Message);
    end;
  finally
    FreeAndNil(FParams);
  end;
end;

procedure TfrmMain.WriteLogProcess(sFunction, sLog: UTF8String);
begin
  if Length(logMemo)>High(Word) then logMemo:='BOM'; //日志达到64k清空
  logMemo:=ConCat(logMemo,Format('%s:[%s]%s',[FormatDateTime('YYYY-MM-DD hh:nn:ss',now),sFunction,sLog]),#13#10);
end;

//------------------------------------------------------------------------------
procedure TfrmMain.InitialFastReport;
begin
  FAjustRuning:=False;
  frxReport:=TfrxReport.Create(self);
  frxReport.OnGetValue := frxReportGetValue;
  frxReport.OnUserFunction := frxReportUserFunction;
  //金额数字转换中文大写的函数
  frxReport.AddFunction('function CallRealToChinese(d:double):String');
  frxOLEObject:=TfrxOLEObject.Create(self);
  frxRichObject:=TfrxRichObject.Create(self);
  frxBarCodeObject:=TfrxBarCodeObject.Create(self);
  frxDialogControls:=TfrxDialogControls.Create(self);
  frxCheckBoxObject:=TfrxCheckBoxObject.Create(self);
  frxGradientObject:=TfrxGradientObject.Create(self);

  frxXLSExport1 := TfrxXLSExport.Create(Self);
  frxRTFExport1 := TfrxRTFExport.Create(Self);
  frxHTMLExport1 := TfrxHTMLExport.Create(Self);
  frxJPEGExport1 := TfrxJPEGExport.Create(Self);
  frxPDFExport1 := TfrxPDFExport.Create(Self);
end;

procedure TfrmMain.InitialHttpClient;
begin
  frmIdHTTPClient.HTTPOptions:=frmIdHTTPClient.HTTPOptions-[hoForceEncodeParams];
  frmIdHTTPClient.Request.Accept:='application/json, text/plain, */*';
  frmIdHTTPClient.Request.AcceptLanguage:='zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6';
  frmIdHTTPClient.Request.UserAgent:='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.46';
  frmIdHTTPClient.Request.ContentType:='application/json;charset=UTF-8';
  frmIdHTTPClient.Request.CustomHeaders.Values['X-COMPANY-CODE']:=DefaultCode;
end;

procedure TfrmMain.InitialHttpServer;
begin
  try
  with frmIdHttpServer.Bindings.Add do
    begin
    IP:=DefaultHost;
    Port:=DefaultPort;
    end;
  frmIdHttpServer.Active:=true;
  except
    on e:exception do
      begin
      frmIdHttpServer.Active:=false;
      WriteLogProcess('InitialHttpServer', e.Message);
      end;
  end;
end;

//  网上抄的：可以到万亿 ， 并且可以随便扩大范围
function RealToChinese(const n: Real): string;
const
  cNum: WideString = '零壹贰叁肆伍陆柒捌玖--万仟佰拾亿仟佰拾万仟佰拾元角分';
  cCha: array[0..1, 0..12] of string = (('零元', '零拾', '零佰', '零仟', '零万', '零亿', '亿万', '零零零', '零零', '零万', '零亿', '亿万', '零元'), ('元', '零', '零', '零', '万', '亿', '亿', '零', '零', '万', '亿', '亿', '元'));
var
  i: Integer;
  sNum, sTemp: WideString;
  sTmpStr: WideString;
begin
  result := '';
  sNum := format('%15d', [round(n * 100)]);

  for i := 0 to 14 do
  begin
    sTemp := copy(sNum, i + 1, 1);
    if sTemp = ' ' then
      continue
    else
      sTmpStr := ConCat(sTmpStr, cNum[strtoint(sTemp) + 1], cNum[i + 13]);
  end;

  for i := 0 to 12 do
    sTmpStr := StringReplace(sTmpStr, cCha[0, i], cCha[1, i], [rfReplaceAll]);

  sTmpStr := StringReplace(sTmpStr, '零角零分', '整', [rfReplaceAll]);
  sTmpStr := StringReplace(sTmpStr, '零分', '', [rfReplaceAll]);

  for i := 1 to Length(sTmpStr) do
    Result := ConCat(Result + ' ', sTmpStr[i]);
end;

function FormatNullDisplay(sTmpStr:String):String;
begin
  Result:='';
  if CompareText(sTmpStr,'null')>0 then Result:=sTmpStr;
end;

function TfrmMain.frxReportUserFunction(const MethodName: string; var Params: Variant): Variant;
begin
  try
    if CompareText(MethodName, 'CallRealToChinese') = 0 then
      Result := RealToChinese(Params[0]);
  except
    on e: Exception do
    begin
      WriteLogProcess('frxReportUserFunction', e.Message);
      Result := '';
    end;
  end;
end;

procedure TfrmMain.frxReportGetValue(const VarName: string; var Value: Variant);
begin
  try
    value:=FPrintParams.S[VarName];
  except
  on e:exception do
    WriteLogProcess('frxReportGetValue', e.Message);
  end;
end;

procedure TfrmMain.ProcessCustomMessage(var msg:tmessage);
begin
  case msg.WParam of
    start_printing:AjustPrintProcess();
  end;
end;

procedure TfrmMain.AjustPrintProcess;
begin
  if FAjustRuning then exit;
  if Length(FPrintData)>0 then
  if TryEnterCriticalSection(FLock) then
    try
      FAjustRuning:=true;
      CoInitialize(nil);
      LoadReportData();
      LoadReportFileProcess();
      PrintReportProcess();
    finally
      CoUninitialize;
      LeaveCriticalSection(FLock);
      FAjustRuning:=false;
    end;
end;

procedure TfrmMain.LoadReportData;
var
  jitem: TSuperObjectIter;
  TmpJson,TmpDataJson:ISuperObject;
begin
  TmpJson:=SO(StringReplace(FPrintData,'null','',[rfReplaceAll, rfIgnoreCase]));
  FPrintMode:=TmpJson.O['params'].I['reportMode'];
  FPrintParams:=TmpJson.O['params'];
  TmpDataJson:=TmpJson.O['tables'];
  if assigned(TmpDataJson) then
    begin
    if ObjectFindFirst(TmpDataJson, jitem) then
      repeat
      SetUserDataSet(jitem.key,jitem.val.AsString);
      until not ObjectFindNext(jitem);
    ObjectFindClose(jitem);
    end;
end;

procedure TfrmMain.LoadReportFileProcess;
var
  sContent:AnsiString;
begin
  try
  FReportStream.Clear;
  sContent:=UTF8Encode(FPrintParams.S['reportContent']);
  FReportStream.Write(sContent[1],Length(sContent));
  if FReportStream.Size=0 then
    begin
    if CompareText(Copy(FPrintParams.S['reportFile'],1,4),'http')=0 then
      frmIdHTTPClient.Get(FPrintParams.S['reportFile'],FReportStream)
      else FReportStream.LoadFromFile(FPrintParams.S['reportFile']);
    end;
  if FReportStream.Size>0 then
    begin
    FReportStream.Position:=0;
    frxReport.LoadFromStream(FReportStream);
    frxReport.PrepareReport;
    end;
  except
  on e:exception do
    WriteLogProcess('LoadReportFileProcess', e.Message);
  end;
end;

procedure TfrmMain.PrintReportProcess;
var
  sExt,sExportFileName:String;
  TmpFilter: TfrxCustomExportFilter;
begin
  try
    if FReportStream.Size>0 then
      begin
      frxReport.ShowProgress:=false;
      frxReport.PrintOptions.ShowDialog := false;
      frxReport.PreviewOptions.Modal := true;
     // frxReport.EngineOptions.SilentMode:=true;
     // frxReport.EngineOptions.NewSilentMode:=simSilent;
      case FPrintMode of
        0:begin
          frxReport.Print;
          end;
        1:begin
          frxReport.EngineOptions.SilentMode:=false;
          frxReport.PrintOptions.ShowDialog := true;
          frxReport.ShowReport;
          end;
        2:begin
          sExportFileName:=FPrintParams.S['exportFile'];
          if Length(sExportFileName)=0 then sExportFileName:=ConCat(FPrintParams.S['reportTitle'],'.pdf');
          sExt:=ExtractFileExt(sExportFileName);
          sExportFileName:=ConCat(ExtractFilePath(Application.ExeName),'export\',sExportFileName);
          TmpFilter:=nil;
          if CompareText(sExt,'.pdf')=0 then TmpFilter := frxPDFExport1;
          if CompareText(sExt,'.xls')=0 then TmpFilter := frxXLSExport1;
          if (CompareText(sExt,'.rtf')=0) or (CompareText(sExt,'.doc')=0) then TmpFilter := frxRTFExport1;
          if (CompareText(sExt,'.jpg')=0) or (CompareText(sExt,'.jpeg')=0) then TmpFilter := frxJPEGExport1;
          if (CompareText(sExt,'.htm')=0) or (CompareText(sExt,'.html')=0) then TmpFilter := frxHTMLExport1;
          if assigned(TmpFilter) then
            begin
            if FileExists(sExportFileName) then
            if not deletefile(sExportFileName) then exit;
            ForceDirectories(ExtractFilePath(sExportFileName));
            TmpFilter.FileName:=sExportFileName;
            TmpFilter.ShowDialog := false;
            TmpFilter.ShowProgress:=false;
            frxReport.export(TmpFilter);
            end;
          end;
        end;
      end;
  except
  on e:exception do
    WriteLogProcess('PrintReportProcess', e.Message);
  end;
end;

procedure TfrmMain.SetUserDataSet(sName:String;sJsonDetia:WideString);
var
  sDataParams:WideString;
  TmpDataBind:PDataBind;
begin
  TmpDataBind:=GetUserDataSet(sName);
  if not Assigned(TmpDataBind) then
     TmpDataBind:=CreateUserDataSet(sName);
  if Assigned(TmpDataBind) then
    begin
    TmpDataBind.TmpDataSet.Close;
    if LoadJsonDataSet(sJsonDetia, sDataParams) then
      TmpDataBind.TmpDataSet.XMLData := sDataParams;
    end;
end;

function TfrmMain.GetUserDataSet(sName:String):PDataBind;
var
  i:Integer;
  TmpObj:PDataBind;
begin
  Result:=nil;
  with TmpDataBindList.LockList do
    try
    for i:=Count downto 1 do
      begin
      TmpObj:=Items[i-1];
      if CompareText(TmpObj.TmpUserData.UserName,sName)=0 then
        begin
        Result:=TmpObj;
        Break;
        end;
      end;
    finally
    TmpDataBindList.UnlockList;
    end;
end;

function TfrmMain.CreateUserDataSet(sName:String):PDataBind;
var
  TmpObj:PDataBind;
begin
  New(TmpObj);
  TmpObj.TmpDataSet:=TClientDataSet.Create(Self);
  TmpObj.TmpUserData:=TfrxDBDataSet.Create(Self);
  TmpObj.TmpUserData.UserName:=sName;
  TmpObj.TmpUserData.DataSet:=TmpObj.TmpDataSet;
  frxReport.DataSets.Add(TmpObj^.TmpUserData);
  TmpDataBindList.Add(TmpObj);
  Result:=TmpObj;
end;

procedure TfrmMain.DeleteDataSetAll;
var
  i:Integer;
  TmpObj:PDataBind;
begin
  frxReport.DataSets.Clear;
  if assigned(TmpDataBindList) then
    begin
    with TmpDataBindList.LockList do
      try
      for i:=Count downto 1 do
        begin
        TmpObj:=Items[i-1];
        if TmpObj.TmpDataSet.Active then
          TmpObj.TmpDataSet.Close;
        freeandnil(TmpObj.TmpDataSet);
        freeandnil(TmpObj.TmpUserData);
        Dispose(TmpObj);
        end;
      finally
      TmpDataBindList.UnlockList;
      end;
    end;
end;

procedure TfrmMain.FinitalFastReport;
begin
  if Assigned(frxPDFExport1) then freeandnil(frxPDFExport1);
  if Assigned(frxJPEGExport1) then freeandnil(frxJPEGExport1);
  if Assigned(frxHTMLExport1) then freeandnil(frxHTMLExport1);
  if Assigned(frxRTFExport1) then freeandnil(frxRTFExport1);
  if Assigned(frxXLSExport1) then freeandnil(frxXLSExport1);

  if Assigned(frxGradientObject) then freeandnil(frxGradientObject);
  if Assigned(frxCheckBoxObject) then freeandnil(frxCheckBoxObject);
  if Assigned(frxDialogControls) then freeandnil(frxDialogControls);
  if Assigned(frxBarCodeObject) then freeandnil(frxBarCodeObject);
  if Assigned(frxRichObject) then freeandnil(frxRichObject);
  if Assigned(frxOLEObject) then freeandnil(frxOLEObject);

  if Assigned(frxReport) then freeandnil(frxReport);
end;

procedure TfrmMain.menu_item_designClick(Sender: TObject);
var
  sContent:AnsiString;
begin
  //如果窗口被缩小进行恢复
  if Assigned(frxReport.Designer)and IsIconic(frxReport.Designer.Handle) then
    ShowWindow(frxReport.Designer.Handle, SW_RESTORE);

  if FAjustRuning then exit;
    try
      FAjustRuning:=true;
      frxReport.DesignReport(true);
      FReportStream.Clear;
      frxReport.SaveToStream(FReportStream);
      FReportStream.Position:=0;
      SetLength(sContent,FReportStream.Size);
      FReportStream.Read(sContent[1],FReportStream.Size);
      Clipboard.AsText:=UTF8Decode(sContent);
    finally
      FAjustRuning:=false;
    end;
end;

procedure TfrmMain.menu_item_exitClick(Sender: TObject);
begin
  ApplicationQuit:=true;
  Close;
end;

procedure TfrmMain.menu_item_logClick(Sender: TObject);
begin
  ShellExecute(GetDeskTopWindow,nil,PChar(Format('http://%s:%d/demo/log.txt',[DefaultHost,DefaultPort])),nil,nil,1);
end;

procedure TfrmMain.menu_item_remoteClick(Sender: TObject);
begin
  menu_item_remote.Checked:=not menu_item_remote.Checked;
  WriteInfor;
end;

procedure TfrmMain.menu_item_testClick(Sender: TObject);
begin
  ShellExecute(GetDeskTopWindow,nil,PChar(Format('http://%s:%d/demo/index.html',[DefaultHost,DefaultPort])),nil,nil,1);
end;

procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose:=ApplicationQuit;
  if not ApplicationQuit then
    Application.Minimize;
end;

procedure TfrmMain.frmApplicationEventsMinimize(Sender: TObject);
begin
  frmMain.Hide;
end;


procedure TfrmMain.ReadInfor;
var
  sFileName:String;
  TmpIniFile:TIniFile;
begin
  sFileName:=ChangeFileExt(Application.ExeName,'.ini');
  if fileexists(sFileName) then
    try
    TmpIniFile:=TIniFile.Create(sFileName);
    DefaultHost:=TmpIniFile.ReadString('Information','DefaultHost','127.0.0.1');
    DefaultPort:=TmpIniFile.ReadInteger('Information','DefaultPort',9521);
    RemotePrintUrl:=TmpIniFile.ReadString('Information','RemotePrintUrl','https://cloud.yhsee.com/api/v1/guest/getOnePrint');
    DefaultCode:=TmpIniFile.ReadString('Information','DefaultCode','Default');
    menu_item_remote.Checked:=TmpIniFile.ReadBool('Information','RemtePrint',false);
    finally
    freeandnil(TmpIniFile);
    end;
end;

procedure TfrmMain.WriteInfor;
var
  sFileName:String;
  TmpIniFile:TIniFile;
begin
  sFileName:=ChangeFileExt(Application.ExeName,'.ini');
  if fileexists(sFileName) then
    try
    TmpIniFile:=TIniFile.Create(sFileName);
    TmpIniFile.WriteBool('Information','RemtePrint',menu_item_remote.Checked);
    finally
    freeandnil(TmpIniFile);
    end;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  logMemo:='BOM';
  WriteLogProcess('日志','开始');
  DefaultPort:=9521;
  DefaultHost:='127.0.0.1';
  ApplicationQuit:=false;
  FReportStream:=TMemoryStream.Create;
  TmpDataBindList:=TThreadList.Create;
  ReadInfor;
  InitialHttpServer;
  InitialFastReport;
  InitialHttpClient;
  FRemotePrintThread:=TCustomThread.Create;
  FRemotePrintThread.OnExecute:=FRemoteOnPrint;
  if not frmIdHttpServer.Active then
    Application.Terminate;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  if assigned(FRemotePrintThread) then
    freeandnil(FRemotePrintThread);
  if assigned(TmpDataBindList) then
    begin
    DeleteDataSetAll;
    freeandnil(TmpDataBindList);
    end;
  if Assigned(FReportStream) then
    FreeAndNil(FReportStream);
  FinitalFastReport;
end;

initialization;
  InitializeCriticalSection(FLock);

finalization;
  DeleteCriticalSection(FLock);

end.
